package com.stx.handler;

import java.io.Serializable;

public class Message implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 同步标记
     */
    public static final int FLAG_ASYNCHRONOUS = 1 << 1;

    /**
     * 消息是否使用的标记
     */
    public static final int FLAG_IN_USE = 1 << 0;

    /**
     * 定义的消息类型
     */
    public int what;

    /**
     * 消息参数1
     */
    public int arg1;

    /**
     * 消息参数2
     */
    public int arg2;

    /**
     * 消息对象参数
     */
    public Object obj;

    /**
     * 消息最终处理类
     */
    public Handler target;

    /**
     * 消息队列的下一个消息
     */
    public Message next;

    /**
     * 消息是否使用的标记
     * 0 - 未使用
     * 1 - 正在使用
     */
    public int flags;


    public long when;

    /**
     * 缓存消息池同步类
     */
    private static final Object sPoolSync = new Object();

    /**
     * 缓存消息池
     */
    private static Message sPool;

    /**
     * 当前缓存消息池大小
     */
    private static int sPoolSize = 0;

    /**
     * 缓存消息池默认大小，最多缓存50个
     */
    private static final int MAX_POOL_SIZE = 50;

    private static boolean gCheckRecycle = true;



    public Message(){
    }

    /**
     * 从缓冲区中获取一个消息类
     * @return
     */
    public static Message obtain(){
        synchronized (sPoolSync){
            if (sPool != null){
                Message m = sPool;
                sPool = m.next;
                m.what = 0;
                m.arg1 = 0;
                m.arg2 = 0;
                m.obj = null;
                m.flags = 0;    //重置为使用状态
                sPoolSize --;
                return m;
            }
        }
        return new Message();
    }

    /**
     * 获取消息，并设置target
     * @param h
     * @return
     */
    public static Message obtain(Handler h) {
        Message m = obtain();
        m.target = h;
        return m;
    }

    /**
     * 获取消息，设置target和what
     * @param h
     * @param what
     * @return
     */
    public static Message obtain(Handler h, int what) {
        Message m = obtain();
        m.target = h;
        m.what = what;

        return m;
    }

    /**
     * 获取消息
     * @param h
     * @param what
     * @param obj
     * @return
     */
    public static Message obtain(Handler h, int what, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.obj = obj;
        return m;
    }

    /**
     * 获取消息
     * @param h
     * @param what
     * @param arg1
     * @param arg2
     * @return
     */
    public static Message obtain(Handler h, int what, int arg1, int arg2) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.arg1 = arg1;
        m.arg2 = arg2;
        return m;
    }

    /**
     * 获取消息
     * @param h
     * @param what
     * @param arg1
     * @param arg2
     * @param obj
     * @return
     */
    public static Message obtain(Handler h, int what,
                                 int arg1, int arg2, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.arg1 = arg1;
        m.arg2 = arg2;
        m.obj = obj;
        return m;
    }

    /**
     * 消息回收, 将不再使用的消息放到消息缓存区
     */
    public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        recycleUnchecked();
    }

    /**
     * 设置同步标记
     * @param async
     */
    public void setAsynchronous(boolean async) {
        if (async) {
            flags |= FLAG_ASYNCHRONOUS;
        } else {
            flags &= ~FLAG_ASYNCHRONOUS;
        }
    }


    /**
     * 消息回收实现(在队列头部插入回收的消息)
     */
    public void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        target = null;
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

    /**
     * 转化成字符串
     * @return
     */
    public String toString(){
        return "what: " + what + " ,arg1: " + arg1 + " ,arg2: " + arg2 + " ,obj: " + obj;
    }

    /**
     * 正在使用，做一个标记
     */
    public void markInUse() {
        flags |= FLAG_IN_USE;
    }

    /**
     * 判断是否同步状态
     * @return
     */
    public boolean isAsynchronous() {
        return (flags & FLAG_ASYNCHRONOUS) != 0;
    }


    public boolean isInUse() {
        return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
    }


}

